package com.kai.steering.data.service.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.kai.steering.common.vo.Result;
import com.kai.steering.common.web.vo.ReturnCodeExt;
import com.kai.steering.data.service.databus.enums.UsableEnum;
import com.kai.steering.data.service.entity.domainObject.RoleDO;
import com.kai.steering.data.service.entity.domainObject.UserDO;
import com.kai.steering.data.service.entity.domainObject.WarehouseDO;
import com.kai.steering.data.service.entity.dto.UserQueryDTO;
import com.kai.steering.data.service.entity.po.Role;
import com.kai.steering.data.service.entity.po.User;
import com.kai.steering.data.service.entity.po.Warehouse;
import com.kai.steering.data.service.entity.vo.UserVO;
import com.kai.steering.data.service.mapper.UserMapper;
import com.kai.steering.data.service.mapper.WarehouseMapper;
import com.kai.steering.data.service.service.RoleService;
import com.kai.steering.data.service.service.UserService;
import com.kai.steering.common.web.service.impl.BaseServiceImpl;
import com.kai.steering.common.vo.Page;

import com.kai.steering.data.service.service.WarehouseService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;

import java.io.Serializable;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import cn.hutool.core.bean.BeanUtil;

import static cn.hutool.core.date.DatePattern.NORM_DATETIME_PATTERN;

/**
 * <pre>
 * 用户 服务实现类
 * </pre>
 *
 * @author kai
 * @since 2022-02-23
 */
@Slf4j
@Service
public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implements UserService   {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private WarehouseService warehouseService;

    @Autowired
    private RoleService roleService;


    @Autowired
    private PasswordEncoder passwordEncoder;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public UserDO saveUser(UserDO userDO) {

        /**
         * 参数检查
         */
        //检查账号
        UserDO userExist = getUserById(userDO.getUserId(),false);
        if (userExist != null || StringUtils.isNotEmpty(userExist.getUserId())) {
            throw ReturnCodeExt.BUSINESS_EXCEPTION.getException(userDO.getUserId() + "账号已存在");
        }

        /**
         * 构建业务对象
         */
        //用户
        User newUser = new User(userDO);
        newUser.setCreationDatetime(new Date());//创建时间
        //仓库
        WarehouseDO warehouseDO = new WarehouseDO(newUser.getUserName() + "主仓库", "主仓库", new Date(), 0);
        warehouseService.saveWarehouse(warehouseDO);//存储仓库
        newUser.setWarehouseId(warehouseDO.getWarehouseId());
        // 加密密码
        String encryptedPassword = passwordEncoder.encode(newUser.getPassword());

        // 设置加密后的密码到用户对象中
        newUser.setPassword(encryptedPassword);
        /**
         * 保存
         */
        super.save(newUser);
        userDO = userDO.convertUserDO(newUser);
        return userDO;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean updateUser(Serializable id, UserDO userDO) {
        /**
         * 参数检查
         */
        //数据不存在
        UserDO old = getUserById(id,false);
        if (old == null || StringUtils.isNotEmpty(old.getUserId())) {
            throw ReturnCodeExt.DAO_EXCEPTION.getException(id + "id不存在");
        }
        /**
         * 服务
         */
        //数据不变
        userDO.setWarehouseId(old.getWarehouseId());
        userDO.setUserId(id.toString());

        /**
         * 构建对象
         */
        User user = new User(userDO);

        // 加密密码
        String encryptedPassword = passwordEncoder.encode(user.getPassword());

        // 设置加密后的密码到用户对象中
        user.setPassword(encryptedPassword);
        return super.updateById(user);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean deleteUser(Serializable id) {
        /**
         * 参数验证
         */
        UserDO userDO = getUserById(id,false);
        if (userDO == null || StringUtils.isEmpty(userDO.getUserId())) {
            throw ReturnCodeExt.DAO_EXCEPTION.getException(id + "id不存在");
        }
        super.removeById(id.toString());
        return true;
    }

    @Override
    public UserDO getUserById(Serializable id ,boolean existenceRole) {
        User user = super.getById(id);
        UserDO userDO = new UserDO(user);
        if (existenceRole){
            List<RoleDO> roleByUser = roleService.getRoleByUser(id.toString(), true);
            userDO.setRoles(roleByUser);
        }
        return userDO;
    }

    @Override
    public UserDO getUserByName(Serializable userName) {
        User user = userMapper.getUserByName(userName);
        UserDO userDO = new UserDO(user);
        return userDO;
    }

    @Override
    public List<UserVO> getAllUser() {
        List<User> userlist = userMapper.selectList(new QueryWrapper<User>().eq("usable", UsableEnum.ACTIVE.getCode()));
        List<UserVO> result = userlist.stream()
                .map(user -> {
                    UserVO userVo = new UserVO();
                    BeanUtil.copyProperties(user, userVo);
                    return userVo;
                })
                .collect(Collectors.toList());
        return result;
    }

    @Override
    public Page<UserVO> getUserPageList(UserQueryDTO userQueryDTO) {
        com.baomidou.mybatisplus.extension.plugins.pagination.Page page = setPageParam(
                userQueryDTO, OrderItem.desc("creation_datetime")
        );//设置排序

        /**
         * 查询参数
         */
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        //存在
        queryWrapper.eq("usable", UsableEnum.ACTIVE.getCode());
        //id
        if (StringUtils.isNotEmpty(userQueryDTO.getUserId())) {
            queryWrapper.eq("user_id", userQueryDTO.getUserId());
        }
        //name
        if (StringUtils.isNotEmpty(userQueryDTO.getUserName())) {
            queryWrapper.like("user_name", userQueryDTO.getUserName());
        }
        //地址
        if (StringUtils.isNotEmpty(userQueryDTO.getAddress())) {
            queryWrapper.like("address", userQueryDTO.getAddress());
        }
        //用户电话
        if (StringUtils.isNotEmpty(userQueryDTO.getPhone())) {
            queryWrapper.like("phone", userQueryDTO.getPhone());
        }
        //开始时间 创建
        if (userQueryDTO.getCreationDateOrigin()==null){
            queryWrapper.ge("creation_datetime", userQueryDTO.getCreationDateOrigin());
        }
        //结束时间 创建
        if (userQueryDTO.getCreationDateTerminus()==null){
            queryWrapper.le("creation_datetime",userQueryDTO.getCreationDateTerminus());
        }
        //开始时间 生日
        if (userQueryDTO.getBirthdayDateOrigin()==null){
            queryWrapper.ge("birthday", userQueryDTO.getBirthdayDateOrigin());
        }
        //结束时间 生日
        if (userQueryDTO.getBirthdayDateTerminus()==null){
            queryWrapper.le("birthday",userQueryDTO.getBirthdayDateTerminus());
        }


        IPage<User> entityPage = userMapper.selectPage(page, queryWrapper);
        List<UserVO> result = entityPage.getRecords().stream()
                .map(user -> {
                    UserVO userVo = new UserVO(user);
                    return userVo;
                })
                .collect(Collectors.toList());

        return Page.<UserVO>builder()
                .currPage(userQueryDTO.getPageNo())
                .pageSize(userQueryDTO.getPageSize())
                .totalCount((int) entityPage.getTotal())
                .list(result)
                .build();
    }


    @Override
    public boolean isExists(String key, String val, Serializable id) {
        QueryWrapper<User> qw = new QueryWrapper<>();
        qw.eq(key, val);
        if (id != null) {
            qw.ne("user_id", id);
        }
        int num = this.count(qw);
        return num > 0;
    }

    @Override
    public UserDO userDtoConvertUserDO(UserQueryDTO userQueryDTO) {
        /**
         * 参数检查
         */
        UserDO userDO = new UserDO();
        userDO.setUserName(userQueryDTO.getUserName());
        userDO.setPassword(userQueryDTO.getPassword());
        userDO.setBirthday(userQueryDTO.getBirthday());
        userDO.setIntroduce(userQueryDTO.getIntroduce());
        userDO.setPhone(userQueryDTO.getPhone());
        userDO.setAddress(userQueryDTO.getAddress());

        return userDO;
    }

    @Override
    @Transactional
    public UserDetails loadUserByUsername(String id) throws UsernameNotFoundException {
        UserDO user = getUserById(id,true);

        // 如果没有找到用户，则抛出一个异常
        if (user == null) {
            throw new UsernameNotFoundException("User not found with username: " + id);
        }
        // 转换用户角色为Spring Security的GrantedAuthority列表
        Collection<? extends GrantedAuthority> authorities = mapRolesToAuthorities(user.getRoles());

        // 创建一个Spring Security的UserDetails对象，并返回它
        // 注意：这里的User不是JPA实体类，而是org.springframework.security.core.userdetails.User
        return new org.springframework.security.core.userdetails.User(
                user.getUserId(), // 用户名
                user.getPassword(), // 密码（这里假设密码已经是加密过的）
                authorities // 用户权限列表
        );
    }

    // 这是一个辅助方法，用于将用户角色转换为Spring Security的GrantedAuthority列表
    private Collection<? extends GrantedAuthority> mapRolesToAuthorities(Collection<RoleDO> roles) {
//        return roles.stream()
//                .map(role -> new SimpleGrantedAuthority("ROLE_" + role.getName().toUpperCase()))
//                .collect(Collectors.toList());

        return roles.stream()
                .flatMap(role -> Stream.concat(
                        // 将角色名转换为 GrantedAuthority
                        Stream.of(new SimpleGrantedAuthority("ROLE_" + role.getName().toUpperCase())),
                        // 将角色关联的权限也转换为 GrantedAuthority
                        role.getPermissions().stream().map(permission -> new SimpleGrantedAuthority(permission.getName()))
                        )
                )
                .collect(Collectors.toList());

    }
}

